/*   CS580 HW   */
#include    "stdafx.h"  
#include	"Gz.h"
#include	"disp.h"


int GzNewFrameBuffer(char** framebuffer, int width, int height)
{
/* create a framebuffer:
 -- allocate memory for framebuffer : (sizeof)GzPixel x width x height
 -- pass back pointer 
*/
	*framebuffer = (char*) operator new (3*width*height);

	return GZ_SUCCESS;
}

int GzNewDisplay(GzDisplay	**display, GzDisplayClass dispClass, int xRes, int yRes)
{
/* create a display:
  -- allocate memory for indicated class and resolution
  -- pass back pointer to GzDisplay object in display
*/
	(*display) = (GzDisplay *) operator new (sizeof(GzDisplay));
	if(xRes<=MAXXRES)
	{
		(*display) -> xres = xRes;
	}
	else
	{
		return GZ_FAILURE;
	}
	if(yRes<=MAXYRES)
	{
		(*display) -> yres = yRes;
	}
	else
	{
		return GZ_FAILURE;
	}
	(*display) -> dispClass = dispClass;
	(*display) -> open = 1;
	(*display) -> fbuf = (GzPixel*) operator new (sizeof(GzPixel)*xRes*yRes);

	return GZ_SUCCESS;
}


int GzFreeDisplay(GzDisplay	*display)
{
/* clean up, free memory */
	delete(display->fbuf);
	delete(display);
	return GZ_SUCCESS;
}


int GzGetDisplayParams(GzDisplay *display, int *xRes, int *yRes, GzDisplayClass	*dispClass)
{
/* pass back values for an open display */
	*xRes = display->xres;
	*yRes = display->yres;
	*dispClass = display->dispClass;

	return GZ_SUCCESS;
}


int GzInitDisplay(GzDisplay	*display)
{
/* set everything to some default values - start a new frame */
	for(int i=0;i<(display->xres*display->yres);i++)
	{
		display->fbuf[i].alpha=255;
		display->fbuf[i].blue=(96<<4);
		display->fbuf[i].green=(112<<4);
		display->fbuf[i].red=(128<<4);
		display->fbuf[i].z=INT_MAX;
	}
	return GZ_SUCCESS;
}


int GzPutDisplay(GzDisplay *display, int i, int j, GzIntensity r, GzIntensity g, GzIntensity b, GzIntensity a, GzDepth z)
{
/* write pixel values into the display */
	int index=ARRAY(i,j);
	if((index>=0)&&(index<(display->xres*display->yres))&&((i>=0)&&(i<display->xres))&&((j>=0)&&(j<display->yres)))//Ensure the pixel in the range of the frame buffer and the location
	{
		display->fbuf[index].alpha=a;
		display->fbuf[index].blue=b;
		display->fbuf[index].green=g;
		display->fbuf[index].red=r;
		display->fbuf[index].z=z;
	}
	return GZ_SUCCESS;
}


int GzGetDisplay(GzDisplay *display, int i, int j, GzIntensity *r, GzIntensity *g, GzIntensity *b, GzIntensity *a, GzDepth *z)
{
	/* pass back pixel value in the display */
	/* check display class to see what vars are valid */
	int index=ARRAY(i,j);
	if((index>=0)&&(index<=(display->xres*display->yres))&&((i>=0)&&(i<display->xres))&&((j>=0)&&(j<display->yres)))//Ensure the pixel in the range of the frame buffer and the location
	{
		*a=display->fbuf[index].alpha;
		*b=display->fbuf[index].blue;
		*g=display->fbuf[index].green;
		*r=display->fbuf[index].red;
		*z=display->fbuf[index].z;
	}
	return GZ_SUCCESS;
}


int GzFlushDisplay2File(FILE* outfile, GzDisplay *display)
{
	/* write pixels to ppm file based on display class -- "P6 %d %d 255\r" */
	char red,blue,green;
	fprintf(outfile,"P6 %d %d 255\r",display->xres,display->yres);//ppm file head
	for(int i=0;i<(display->xres*display->yres);i++)
	{
		red=display->fbuf[i].red;
		if(display->fbuf[i].red>=4095)//if the red color is larger than the range, cut down to the maximum
		{
			red=255;
		}
		else
		{
			red=display->fbuf[i].red>>4;//reduce to 8 bit
		}
		fprintf(outfile,"%c",red);
		green=display->fbuf[i].green;
		if(display->fbuf[i].green>=4095)//if the green color is larger than the range, cut down to the maximum
		{
			green=255;
		}
		else
		{
			green=display->fbuf[i].green>>4;//reduce to 8 bit
		}
		fprintf(outfile,"%c",green);
		blue=display->fbuf[i].blue;
		if(display->fbuf[i].blue>=4095)//if the blue color is larger than the range, cut down to the maximum
		{
			blue=255;
		}
		else
		{
			blue=display->fbuf[i].blue>>4;//reduce to 8 bit
		}
		fprintf(outfile,"%c",blue);
	}

	return GZ_SUCCESS;
}

int GzFlushDisplay2FrameBuffer(char* framebuffer, GzDisplay *display)
{
	/* write pixels to framebuffer: 
		- Put the pixels into the frame buffer
		- Caution: store the pixel to the frame buffer as the order of blue, green, and red 
		- Not red, green, and blue !!!
	*/
	char red,blue,green;
	int i,j;
	for(i=0,j=0;i<(display->xres*display->yres);i++)
	{
		blue=display->fbuf[i].blue;
		if(display->fbuf[i].blue>=4095)//if the red color is larger than the range, cut down to the maximum
		{
			blue=255;
		}
		else
		{
			blue=display->fbuf[i].blue>>4;//reduce to 8 bit
		}
		framebuffer[j]=blue;
		j++;
		green=display->fbuf[i].green;
		if(display->fbuf[i].green>=4095)//if the green color is larger than the range, cut down to the maximum
		{
			green=255;
		}
		else
		{
			green=display->fbuf[i].green>>4;//reduce to 8 bit
		}
		framebuffer[j]=green;
		j++;
		red=display->fbuf[i].red;
		if(display->fbuf[i].red>=4095)//if the blue color is larger than the range, cut down to the maximum
		{
			red=255;
		}
		else
		{
			red=display->fbuf[i].red>>4;//reduce to 8 bit
		}
		framebuffer[j]=red;
		j++;
	}

	return GZ_SUCCESS;
}